<?php

namespace Swof\Server\Socket;

use Swof\Http\WebSocketRequest;
use Swoole\Server;
use Swoole\WebSocket\Frame;
use Swof\Server\Http\HttpServer;
use Swoole\Http\Request as SwoRequest;
use Swoole\Http\Response as SwoResponse;
use Swoole\WebSocket\Server as SwoWsServer;

class WebSocketServer extends HttpServer
{
    /**
     * Note: 初始化事件
     *
     * @author: Zhao Zhiqiang
     * @since: 2021/5/11 17:25
     */
    protected function initEvent()
    {
        $this->setEvent('sub', [
            'request' => 'onRequest',
            'handshake' => 'onHandshake',
            'open' => 'onOpen',
            'message' => 'onMessage',
            'close' => 'onClose'
        ]);
    }

    /**
     * Note: 创建 Http 服务器
     *
     * @return mixed|void
     * @author: Zhao Zhiqiang
     * @since: 2021/5/11 17:29
     */
    public function createServer()
    {
        $this->swoServer = new SwoWsServer(
            config('server.http.host'),
            config('server.http.port')
        );
    }

    public function onHandshake(SwoRequest $swoRequest, SwoResponse $swoResponse)
    {
        $this->app->make('event')->trigger('ws.hand', [$this, $swoRequest, $swoResponse]);

        $this->onOpen($this->swoServer, $swoRequest);
    }

    public function onOpen(SwoWsServer $swoServer, SwoRequest $swoRequest)
    {
        $request = WebSocketRequest::initialize($swoRequest)
            ->setMethod('OPEN')
            ->setRequestUri($swoRequest->server['path_info']);

        app('router')->dispatchToRoute($request, [$swoServer, $swoRequest]);
    }

    public function onMessage(SwoWsServer $swoServer, Frame $frame)
    {
        $request = app('wsRequest')
            ->setMethod('MESSAGE')
            ->setRequestUri(WebSocketRequest::get($frame->fd)['path']);

        $this->app->make('event')->trigger('ws.message.before', [$this, $swoServer, $frame]);

        // 信息的业务流程
        app('router')->dispatchToRoute($request, [$swoServer, $frame]);
    }

    public function onClose(Server $swoServer, int $fd)
    {
        $this->app->make('event')->trigger('ws.close', [$this, $swoServer, $fd]);
        WebSocketRequest::del($fd);

        dd('客户端关闭了');
    }

    /**
     * 群发
     *
     * @param array $data
     */
    public function sendAll(array $data)
    {
        $connections = $this->swoServer->connections;

        foreach ($connections as $fd) {
            if ($this->swoServer->isEstablished($fd)) {
                $this->swoServer->push($fd, json_encode($data, 256));
            }
        }
    }
}